#include "onb.h"
#include <util.h>

Onb::Onb(const Vec3&n)
{
    axis[2] = unit_vector(n);
    Vec3 a = (std::fabs(axis[2].x()) > 0.9) ? Vec3(0, 1, 0) : Vec3(1, 0, 0);
    axis[1] = unit_vector(cross(axis[2], a));
    axis[0] = cross(axis[2], axis[1]);
}

Vec3 Onb::local(double a, double b, double c) const
{
	return a * u() + b * v() + c * w();
}

Vec3 Onb::local(const Vec3& a) const
{
	return a.x() * u() + a.y() * v() + a.z() * w();
}

Vec3 Onb::transform(const Vec3& v) const
{
    return (v[0] * axis[0]) + (v[1] * axis[1]) + (v[2] * axis[2]);
}

void Onb::build_from_w(const Vec3& w)
{
    Vec3 unit_w = unit_vector(w);
    Vec3 a = (fabs(unit_w.x()) > 0.9) ? Vec3(0, 1, 0) : Vec3(1, 0, 0);
    Vec3 v = unit_vector(cross(unit_w, a));
    Vec3 u = cross(unit_w, v);
    axis[0] = u;
    axis[1] = v;
    axis[2] = unit_w;
}
